js-11 事件对象
一、事件
事件函数:事件要调用的函数;
事件处理函数:事件触发时要执行的函数;
事件对象:事件发生时,与这个事件有关的信息保存的一个对象;
当一个事件发生时,将有关信息保存在事件函数的内置全局对象event当中,可以直接使用,包括事件类型,操作对象,鼠标位置;
常用的内置对象:
type
:获取事件类型;target
(srcElement(ie8-)):获取触发事件的对象;clientX/Y
:鼠标到文档可视区的坐标点;offsetX/Y
:当前位置距离上一个定位元素的距离screenX/Y
:当前位置距离屏幕的坐标点pageX/Y
,鼠标到文档的距离,包括滚动的地方;ie8以下没有;e.button
0是鼠标左键,1是滚动按下 2是鼠标右键
IE/谷歌:使用事件函数内的内置对象;
标准浏览器:使用事件函数的第一个参数形参;
做兼容:
//如果不做ie8兼容,就可以不用写
div.onclick = function(ev){
var ev = ev || window.event;
}
二、事件绑定
- 定义:在一个元素上绑定多个事件,不会覆盖,都会执行;
obj.addEventListener("click",fn,false)
; 标准,true(捕获),false(冒泡);this指向自己;
事件不需要加on,事件处理函数,布尔值); 缺点:不兼容IE;
- 元素.
attachEvent
(事件(要加on),事件处理函数);只有冒泡;倒序执行;IE8及以下;非标准;this指向window;
做兼容:
function setEvent(obj,even,fn){ //元素,事件,事件处理函数;
if(obj.attachEvent){
obj.attachEvent("on" + even,fn);
}else{
obj.addEventListener(even,fn,true);
}
}
标准浏览器的事件绑定和 ie 浏览器的事件绑定的区别:
(1)ie 没有捕获,标准有捕获
(2)ie 的事件名称前面有 on,标准没有
(3)标准的 ie 会根据事件的顺序正序执行,非 ie 标准逆序,标准正序
(4)ie 的 this 是 window,标准的是触发这个事件的对象
(4)标准浏览器的事件绑定和 ie 浏览器的事件绑定是不共存的,因此我们需要进行一个兼容的操作,一般情况下,如果是两个方法的兼容,那么就拿出其中一个方法,在各个浏览器中查看获取的值,标准浏览器和 ie 浏览器会得到不一样的结果。
三、取消事件绑定
取消事件绑定最好明确函数的名字,不然会有很多不确定的因素;
- 普通的:元素.onclick = null;
- addEventListener事件函数:
removeEventListener
("事件",事件处理函数); - attachEvent事件函数:
detachEvent
("事件",事件处理函数);
四、事件流
捕获: 当父元素和子元素都绑定了事件,先触发父元素,再触发子元素,从外到内;
冒泡: 先触发子元素再触发父元素,从内到外;
事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即 DOM 事件流。
DOM 事件流会有 3 个阶段:
事件捕获阶段:事件的传播是从最不特定的事件目标到最特定的事件目标。即从 DOM树的根到叶子。
确定目标阶段:通过捕获确定具体触发事件的元素
事件冒泡阶段:事件的传播是从最特定的事件目标到最不特定的事件目标。即从 DOM树的叶子到根。
五、阻止冒泡事件(掌握)
问题:子元素设置事件,再给其父元素设置事件,当触发子元素事件的时候,其父元素的事件也触发了,子元素监听到触发事件,所有包含事件的父元素都会触发;
阻止:
event.stopPropagation()
;IE8以下不兼容; Propagation 传播传递
event.cancelBubble=true
;IE8以下兼容; Bubble冒泡,cancel取消;
做兼容:
event.stopPropagation ? event.stopPropagation() : window.event.cancelBubble = true;
注意:不是所有的事件都能冒泡,blur
、focus
、load
、unload
不能冒泡;
六、事件委托
- 将子元素要做的事情委托给父元素;
event.target
; - 使用场景:子元素很多,事件相同的使用,后添加的相同元素会有相同的脚本;
- 原理:事件委托是利用事件冒泡原理来实现的,因为点击子元素会冒泡到父元素,那么给父元素做点击事件,里面的元素做点击事件时,都会冒泡到父元素身上,这就是事件委托,委托它们的父级代为执行事件;
- 事件委托实现:将事件添加到父元素上,当事件发生时,父元素会找到对应触发事件的子元素去处理,后期添加的子元素,依然有这个事件。
事件源不兼容IE8-,IE8支持:event.srcElement
;
事件源兼容:
var target = ev.target || ev.srcElement;
七、取消事件默认行为
return false
;对事件绑定设置的不起作用,也可以直接使用以下的两种;- 事件绑定的阻止默认行为:
event.preventDefault()
; - IE事件绑定:
event.returnValue = false
;
总结:
事件绑定 | 取消事件绑定 | 阻止事件冒泡 | 事件委托 | 取消默认行为 | |
---|---|---|---|---|---|
通常 | obj.事件=函数 | onclick = null | return false | ||
标准浏览器 | addEventListener | removeEventListener | stopPropagation | event.target | event.preventDefault() |
非标准浏览器 | attachEvent | detachEvent | cancelBubble | event.srcElement | event.returnValue = false; |
八、键盘事件
onkeydown
;按下;不区分大小写onkeyup
;抬起;onkeypress
;比onkeydown后触发,区分大小写,只能包含数字和字母,大小写是反过来的;不能获取到功能键,如箭头;
键盘值: event.key
获得按下的键;
event.keyCode
获得按下的键码值,字母为大写的Unicode码;
event.shiftKey
;是否按下shift键,返回布尔值;
event.ctrlKey
;是否按下ctrl键;
event.altKey
;是否按下alt键;
- 扩展
compositionstart
中文输入法输入开始时触发。
compositionend
中文输入法输入结束时触发。
九、鼠标滚轮事件:
元素.onmousewheel
滚动的时候触发;
event.wheelDelta
:120向上滚动;-120向下滚动;
火狐浏览器需要通过绑定事件获取:
div.addEventListener("DOMMouseScroll",事件处理函数)
;
event.detail
:-3向上滚动,3向下滚动;
十、customEvent事件
自定义事件,就跟vue里面的on跟emit一样
监听自定义事件
window.addEventListener('follow',event=>{
console.log(event.detail) // {name:'前端'}
})
派发自定义事件
window.dispatchEvent(new CustomEvent('follow',{
detail:{
name:'前端'
}
}))
例子:
var div = document.createElement('div')
div.click = function(){
console.log('被点击了111111')
}
var click = new Event('click')
div.dispatchEvent(click)
十一、监控事件
- 使用
monitorEvents
侦听特定类型的事件。 - 使用
unmonitorEvents
停止侦听。 - 使用
getEventListeners
获取 DOM 元素的所有事件 - 使用
“Event Listeners Inspector”
面板获取有关事件侦听器的信息。
获取元素绑定的事件对象:getEventListeners(元素)
; 需要在控制台打印:
监控元素上的事件命令: monitorEvents
和 unmonitorEvents
monitorEvents(元素,[可选的事件名字])
monitorEvents(document,'click')
十二、try catch
用来捕获出错的代码,try..catch只能捕获同步代码,不能捕获异步代码的错误;
如果出错了,则不能执行下面的步骤,因此可以使用try来捕获错误
try{
//可能成功的事件
} catch (e) {
//捕获错误
} finally {
// 无论成功于否都会执行
}
高频面试题
● 事件、IE 与火狐的事件机制有什么区别?
● 如何阻止冒泡?
● 事件绑定和普通事件有什么区别。
● 如何用原生 js 给元素绑定两个 click 事件?
● 解释一下事件流?
● 事件委托是什么。
● 给 10000 个 li 添加点击事件。